package org.ala.tiktools.sharddb.mybatis.double_write.impls;

import java.lang.reflect.Method;
import java.util.Map;
import java.util.concurrent.ThreadPoolExecutor;

import org.ala.tiktools.sharddb.mybatis.double_write.IDoubleWriter;
import org.ala.tiktools.sharddb.mybatis.executor.ShardExecutor;
import org.ala.tiktools.sharddb.mybatis.executor.ShardTxExecutor;
import org.ala.tiktools.sharddb.mybatis.interceptor.Shard;
import org.ala.tiktools.sharddb.mybatis.router.ShardInfo;
import org.ala.tiktools.sharddb.mybatis.transaction.ShardTransaction;
import org.ala.tiktools.tools.CachingKVTools;
import org.ala.tiktools.tools.thread_pool.ThreadPoolTools;


/**
 * 默认的双写执行器
 * <p>  在原线程中直接执行method
 *
 * @author ala
 * @date 2025-02-27 13:40
 */
public class DefaultDoubleWriter implements IDoubleWriter {
    /**
     *  事务执行器
     */
    protected ShardTxExecutor txExecutor = new ShardTxExecutor();


    @Override
    public void invoke(Object proxy, Method method, Map<ShardInfo, Object[]> args, Map<ShardInfo, ShardExecutor.Result> results) {
        Shard anno = method.getAnnotation(Shard.class);
        ShardTransaction txAnno = method.getAnnotation(ShardTransaction.class);
        txExecutor.doShardInvokeWithTx(anno, txAnno, threadPoolMapper.get(method), args, proxy, method);
    }


    /**
     *  公共业务线程池
     */
    protected ThreadPoolExecutor commonThreadPool = ThreadPoolTools.build(5, 20, 1024, "shard_db_commons_thread");
    /**
     *  方法绑定的线程池
     */
    protected CachingKVTools<Method, ThreadPoolExecutor> threadPoolMapper = new CachingKVTools<>(ThreadPoolTools.NULL, m -> {
        Shard anno = m.getAnnotation(Shard.class);
        if (anno.coreSize() <= 0 || anno.maxSize() <= 0 || anno.queueSize() <= 0) {return commonThreadPool;}
        return ThreadPoolTools.build(anno.coreSize(), anno.maxSize(), anno.queueSize(), String.format("%s_%s_shard_thread", m.getDeclaringClass().getSimpleName(), m.getName()));
    });
}
